<template>
  <div class="permission-edit">
    <div class="page-box-row-left">
      <FormBlock
        :title="$t('module.menu.assignableFunction')"
        direction="column"
        style="width: 44%; max-width: 320px; overflow-x: hidden;"
        height="435px"
      >
        <el-tree
          class="treeStyle"
          :data="baseData"
          :show-checkbox="true"
          ref="resourceTree"
          icon-class="ivu-icon-ios-arrow-forward"
          :props="treeProps"
          node-key="key"
          :check-strictly="false"
          :default-checked-keys="defaultCheckedKeys"
        >
          <!-- @check="check" -->
          <span class="custom-tree-node" slot-scope="{ node, data }">
            <span>
              <Icon type="lightbulb" v-if="data.menuType == '2'" />
              <Icon type="navicon-round" v-if="data.menuType == '1'" />
              <Icon type="ios-ionic-outline" v-if="data.menuType == '0'" />
              <Icon type="android-home" v-if="data.resourceType == '1'"></Icon>
              <Icon type="android-cloud-outline" v-if="data.resourceType == '2'"></Icon>
              <Icon type="android-cloud" v-if="data.isPublicAPI"></Icon>
              {{ node.label }}
            </span>
          </span>
        </el-tree>
      </FormBlock>
      <div class="operation-area">
        <Button @click="append"  :loading="loading">
          {{ $t("module.menu.allocation") }}
          <Icon type="ios-arrow-forward" />
        </Button>
        <Button @click="remove" >
          <Icon type="ios-arrow-back" />
          {{ $t("module.menu.remove") }}
        </Button>
      </div>
      <FormBlock
        :title="$t('module.menu.assignedFeature')"
        direction="column"
        style="width: 45%; max-width: 330px; overflow-x: hidden; float: right;"
        height="435px"
      >
        <el-tree
          class="assignedTree treeStyle"
          :data="assignedData"
          :show-checkbox="true"
          ref="assignedTree"
          :props="treeProps"
          node-key="key"
          :check-strictly="false"
          :expand-on-click-node="false"
        >
          <span class="custom-tree-node" slot-scope="{ node, data }">
            <span>
              <Icon type="lightbulb" v-if="data.menuType == '2'" />
              <Icon type="navicon-round" v-if="data.menuType == '1'" />
              <Icon type="ios-ionic-outline" v-if="data.menuType == '0'" />
              <Icon type="android-home" v-if="data.resourceType == '1'"></Icon>
              <Icon type="android-cloud-outline" v-if="data.resourceType == '2'"></Icon>
              <Icon type="android-cloud" v-if="data.isPublicAPI"></Icon>
              {{ node.label }}
            </span>
            <Input
              v-model="data.attributeValue"
              :placeholder="$t('module.menu.accessParameter')"
              style="width: 100%;"
              
              v-if="data.menuType == '0'"
              @on-change="onAttributeChange(data)"
            />
            <span class="attribute-read-only" v-if="data.menuType == '0'">{{ data.attributeValue }}</span>
          </span>
        </el-tree>
      </FormBlock>
    </div>
    <Spin size="large" fix v-if="isQuery"></Spin>
  </div>
</template>
<script>
import menuAPI from "@/api/menuAPI.js";
import { searchAppList } from "@/api/applicationApi.js";
import locales from "./locales.js";
import roleApi from "@/api/roleApi.js";
import { PATH_HOME } from "@/const";

export default {
  name: "permissionedit",
  mixins: [locales],
  props: {
    menuId: {
      type: String,
      default() {
        return "";
      }
    }
  },
  data() {
    return {
      fun: null,
      appList: {},
      baseData: [],
      assignedData: [],
      isRightTree: false,
      checkedList: [],
      defaultCheckedKeys: [], //已分配节点为选中状态
      changedData: new Map(),
      treeProps: {
        label: "title",
        children: "children"
      },
      isQuery: false,
      loading: false
    };
  },
  computed: {},
  created: function () {
    this.init();
    this.$emit("SetTitle", this.$t("module.menu.permissionMaList"));
    this.$emit("SetPageWidth", 820);
    // this.$emit("SetPageActions", this.actions);
  },
  beforeMount: function () {},
  mounted: function () {},
  beforeDestroy: function () {},
  destroyed: function () {},
  methods: {
    async init() {
      this.isQuery = true;

      const [
        {
          data: { records }
        },
        resourceTree,
        assignedTree
      ] = await Promise.all([
        searchAppList({ pageNum: 1, pageSize: 200 }),
        menuAPI.queryResourceTree(this.menuId),
        menuAPI.queryAssignedResourceTree(this.menuId)
      ]);
      this.isQuery = false;

      // 初始化应用
      this.initApplication(records);

      // 初始化已分配资源树
      this.isRightTree = true;
      const assignedData = this.initChildren(assignedTree) || [];
      this.assignedData = this.groupByApp(assignedData);
      // 初始化资源树
      this.isRightTree = false;
      const baseData =
        this.initChildren(
          resourceTree.filter(item => {
            // 过滤掉空目录、隐藏功能
            if ((item.menuType == "1" && item.menuChildren.length == 0) || item.isShow == 0) {
              return false;
            } else {
              return true;
            }
          })
        ) || [];
      this.baseData = this.groupByApp(baseData);
    },
    // 获取应用
    initApplication(records) {
      records.forEach(app => {
        this.appList[app.clientId] = app.appName;
      });
    },
    // 获取资源树
    queryResourceTree() {
      menuAPI.queryResourceTree(this.menuId).then(treeData => {
        this.isRightTree = false;
        // 当移除已分配节点去重新获取左侧资源树时，清空已分配节点在左侧资源树的选中状态
        this.defaultCheckedKeys = [];
        const baseData =
          this.initChildren(
            treeData.filter(item => {
              // 过滤掉空目录、隐藏功能
              if ((item.menuType == "1" && item.menuChildren.length == 0) || item.isShow == 0) {
                return false;
              } else {
                return true;
              }
            })
          ) || [];
        this.baseData = this.groupByApp(baseData);
      });
    },
    // 获取资源树
    queryAssignedResourceTree() {
      menuAPI.queryAssignedResourceTree(this.menuId).then(treeData => {
        this.isRightTree = true;
        const assignedData = this.initChildren(treeData) || [];
        this.assignedData = this.groupByApp(assignedData);
      });
    },
    groupByApp(datas) {
      // 功能按应用分类
      const source = datas.reduce((apps, item) => {
        Array.isArray(apps[item.applicationCode]) || (apps[item.applicationCode] = []);
        // apps[item.applicationCode].push(item);
        // isShow: 1和null为显示功能（存在的功能）,0为隐藏功能（不存在的功能）
        if (item.isShow != 0) {
          apps[item.applicationCode].push(item);
        }
        return apps;
      }, {});
      //
      const newDatabase = [];
      for (const [key, val] of Object.entries(source)) {
        newDatabase.push({
          id: key == "" ? "public" : key,
          key: key == "" ? "public" : key,
          title: key == "" ? this.$t("module.menu.publicFunction") : this.appList[key] || key,
          children: val,
          first: true
        });
      }
      return newDatabase;
    },
    initChildren(children, isDisabled) {
      let deleteIndex = null;
      children.forEach((node, index) => {
        node.key = node.id;
        if (node.menuType == "1") {
          // 当前节点是菜单目录
          node.children = this.initChildren(node.menuChildren);
          node.title = node.menuName;
        } else if (node.menuType == "0") {
          // 当前节点是首页，移除当前节点
          if (node.actionUrl == PATH_HOME) {
            // node.disabled = true;
            // this.defaultCheckedKeys.push(node.id);
            deleteIndex = index;
            return;
          }
          // 当前节点是菜单
          // node.children = this.initChildren(node.resourceChildren, node.disabled);
          node.children = this.initChildren(node.resourceChildren);
          node.title = node.menuName;

          // // 已分配节点不可勾选
          // if (!this.isRightTree) {
          //   node.disabled = this.isAssignedNode(this.assignedData, node);
          //   // 已分配节点为选中状态
          //   if (node.disabled == true) {
          //     this.defaultCheckedKeys.push(node.id);
          //   }
          // }
        } else if (node.resourceType) {
          // 当前节点是资源
          node.children = this.initChildren(node.resourceChildren);
          node.title = node.resourceName;
          // 父节点已禁用，当前节点禁用
          // if (isDisabled) {
          //   node.disabled = isDisabled;
          //   this.defaultCheckedKeys.push(node.id);
          // }

          // // 已分配节点不可勾选
          // if (!this.isRightTree) {
          //   node.disabled = this.isAssignedNode(this.assignedData, node);
          //   // 已分配节点为选中状态
          //   if (node.disabled == true) {
          //     this.defaultCheckedKeys.push(node.id);
          //   }
          // }

          // 当前节点是API资源
          if (node.resourceType == 2) {
            // 使用父Id+子Id作为key
            // 因为有资源挂载功能，API资源可能重复出现，导致id相同的节点出现
            node.key = node.parentResourceId + node.id;
          }
        } else {
          // 当前节点是未知类型
          node.children = this.initChildren(node.menuChildren);
          node.title = node.menuName;
        }
        // 勾选的节点
        if (node.selected == 1) {
          this.checkedList.push(node.key);
        }
      });
      // 移除节点
      if (deleteIndex != null) children.splice(deleteIndex, 1);

      return children;
    },
    // 是否已分配节点
    isAssignedNode(children, node) {
      let child = children.find(child => {
        if (child.id == node.id) {
          return true;
        } else {
          if (child.children && child.children.length > 0) {
            return this.isAssignedNode(child.children, node);
          } else {
            return false;
          }
        }
      });
      return !!child;
    },
    append() {
      this.loading = true;
      // 返回所有选择和半选择的节点
      let checkedList = this.$refs["resourceTree"].getCheckedNodes(false,true);
      if (checkedList && checkedList.length == 0) {
        this.$message.error({
          content: this.$t("common.warning.selctAddElement"),
          duration: 3
        });
        this.loading = false;

        return;
      }
      let functions = [];
      let functionIds = [];
      let resourceIds = [];
      for (let item of checkedList) {
        if (!!item.menuType) {
          // 功能
          functions.push({ menuId: this.menuId, functionId: item.id, attributeValue: item.attributeValue });
        } else if (!!item.resourceType) {
          // 资源
          resourceIds.push(item.id);
          // 查找资源的父功能节点
          this.findParentFunction(item, parentNode => {
            // 如果父功能未选中
            if (!parentNode.checked && !functionIds.includes(parentNode.data.id)) {
              functionIds.push(parentNode.data.id);
              // 将父功能当作选中项
              functions.push({
                menuId: this.menuId,
                functionId: parentNode.data.id,
                attributeValue: parentNode.data.attributeValue
              });
            }
          });
        }
      }
      // 没有选择资源 且 没有选择功能 时不提交
      if (resourceIds && resourceIds.length == 0 && functions && functions.length == 0) {
        this.loading = false;
        return;
      }
      let params = {
        menuId: this.menuId,
        menuFunctionRels: functions,
        resourceId: resourceIds
      };
      menuAPI.addAssignedResource(params).then(data => {
        this.$message.success({
          content: this.$t("module.menu.warning.allocatingResourceSuccess"),
          duration: 3
        });
        // this.loading = false;
        // 获取资源树
        this.queryAssignedResourceTree();
        // 获取资源树
        this.queryResourceTree();
        this.$nextTick(() => {
          this.loading = false;
        });
      });
    },
    remove() {
      let checkedList = this.$refs["assignedTree"].getCheckedNodes();
      if (checkedList && checkedList.length == 0) {
        this.$message.error({
          content: this.$t("common.warning.selctRemoveElement"),
          duration: 3
        });
        return;
      }
      // 获取功能组引用到的角色
      let param = {
        menuIds: [this.menuId]
      };
      let roleByMenu = [];
      roleApi.getRoleByMenu(param).then(res => {
        res.map(item => {
          roleByMenu.push(item.roleName);
        });
        // 删除提示：如果该删除的功能组有引用的角色，则显示严重提示，否则不显示提示
        let deleteTip =
          roleByMenu.length != 0
            ? [
                this.$t("module.menu.warning.confirmRemove"),
                this.$t("module.menu.warning.influenceRole") + ":" + roleByMenu
              ]
            : "";
        // 调用移除(数组则代表显示严重提示，为空则为不显示提示)
        if (deleteTip) {
          this.$confirm.swarning(deleteTip).then(() => {
            this.onRemoveAction(checkedList);
          });
        } else {
          this.onRemoveAction(checkedList);
        }
      });
    },
    onRemoveAction(checkedList) {
      let functions = [];
      let functionIds = [];
      let resourceIds = [];
      for (let item of checkedList) {
        if (!!item.menuType) {
          // 功能
          functionIds.push(item.id);
        } else if (!!item.resourceType) {
          // 资源
          resourceIds.push(item.id);
        }
      }
      let params = {
        menuId: this.menuId,
        functionId: functionIds,
        resourceId: resourceIds
      };
      menuAPI.deleteAssignedResource(params).then(data => {
        this.$message.success({
          content: this.$t("module.menu.warning.removeResourceSuccess"),
          duration: 3
        });
        // 获取资源树
        this.queryAssignedResourceTree();
        // resourceIds.forEach(id => {
        //   this.$refs["assignedTree"].remove(id);
        // });
        // functionIds.forEach(id => {
        //   this.$refs["assignedTree"].remove(id);
        // });
        // 获取资源树
        this.queryResourceTree();
      });
    },

    onAttributeChange(data) {
      if (!this.changedData.get(data.id)) {
        this.changedData.set(data.id, data);
      }
    },
    // 查找资源的父功能
    findParentFunction(resource, todo) {
      if (resource.functionId) {
        let parentNode = this.$refs["resourceTree"].getNode(resource.functionId);
        todo(parentNode);
      }
    }
  },
  watch: {},
  directives: {}
};
</script>

<style lang="less">
.permission-edit {
  .page-box-row-left {
    // .el-tree > div > div > label {
    //   display: none;
    // }
    .operation-area {
      // width: 75px;
      width: 8%;
      max-width: 55px;
      padding-left: 6px;
      position: relative;
      // float: left;
      display: inline-block;
      // margin: 0 16px;
      vertical-align: middle;
      margin: 200px auto 0px auto;
      button {
        border-radius: 0;
      }
      button:first-child {
        color: #fff;
        background-color: #ff6f4b;
        border-color: #ff6f4b;
        margin-bottom: 16px;
      }

      button:not(:first-child) {
        color: #ff6f4b;
        background-color: #ffffff;
        border-color: #ff6f4b;
      }
    }
    .assignedTree {
      .ivu-input-wrapper {
        display: none;
      }
      .ivu-input-small {
        height: 22px;
        font-size: 12px;
      }
      .attribute-read-only {
        width: 100%;
        padding-left: 8px;
      }
      .el-tree-node__content:hover {
        .ivu-input-wrapper {
          display: inline-block;
        }
        .attribute-read-only {
          width: 100%;
          padding-left: 8px;
          display: none;
        }
      }
    }
  }
}
</style>
